﻿using AutoMapper;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using XfTechOAWeb.Data.Base;
using XfTechOAWeb.Dtos;
using XfTechOAWeb.Dtos.AutoMapperConfig;
using XfTechOAWeb.Dtos.Dicts;
using XfTechOAWeb.EFCore.Extensions;
using XfTechOAWeb.Infrastructure.Utilities;
using XfTechOAWeb.IService.Base;
using XfTechOAWeb.Models.Base;

namespace XfTechOAWeb.Service.Base
{
    /// <summary>
    /// 应用服务抽象基类（单实体CRUD）
    /// </summary>
    /// <typeparam name="Tkey">主键类型</typeparam>
    /// <typeparam name="TEntityDto">用户显示的输出用Dto</typeparam>
    /// <typeparam name="TAddUpdateDto">添加和修改的输入用DTO</typeparam>
    /// <typeparam name="TPagingDto">分页DTO</typeparam>
    public abstract class BaseService<TEntity, Tkey, TEntityDto, TAddUpdateDto, TPagingDto> 
        :IBaseService<Tkey, TEntityDto, TAddUpdateDto, TPagingDto>
                where TEntity : class
                where Tkey : struct
                where TEntityDto : class
                where TAddUpdateDto : class
                where TPagingDto : PageRequestModel
    {
        private readonly IRepository<TEntity> _repository;
        private readonly IMapper _mapper;

        /// <summary>
        /// 获取当前用户
        /// </summary>
        public string CurrentUserName
        {
            get 
            {
                return AppHttpContext.Current.User.FindFirst(
                                        x => x.Type == ClaimTypes.Name).Value ?? "admin";
            }
        }

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="repository">仓储接口注入</param>
        public BaseService(IRepository<TEntity> repository)
        {
            _repository = repository; //注入仓储

            //配置AutoMapper，并实例化Mapper
            var mapperConfiguration = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<ModelToDtoMapperProfile>();
            });
            _mapper = new Mapper(mapperConfiguration);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public virtual List<TEntityDto> GetList()
        {
            var list = _repository.Table.ToList();

            return _mapper?.Map<List<TEntityDto>>(list);
        }

        /// <summary>
        /// 获取分页列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public virtual PageResponseModel<TEntityDto> GetPagedList(TPagingDto input)
        {
            //根据排序字段名、升序/降序，进行排序
            var query = _repository.Table;
            if (input.SortType.Equals("ASC"))
            {
                query = query.OrderBy(input.SortedBy)
                            .Skip((input.PageIndex - 1) * input.PageSize)
                            .Take(input.PageSize);
            }
            else
            {
                query = query.OrderByDescending(input.SortedBy)
                        .Skip((input.PageIndex - 1) * input.PageSize)
                        .Take(input.PageSize);
            }

            var pagedList = new PageResponseModel<TEntityDto>();
            pagedList.PageList = _mapper.Map<List<TEntityDto>>(query.ToList());
            pagedList.TotalCount = _repository.Table.Count();

            return pagedList;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public virtual int Insert(TAddUpdateDto input)
        {
            TEntity model = _mapper.Map<TEntity>(input);
            //判断是否带审计属性
            if(typeof(TEntity).IsSubclassOf(typeof(AuditedEntity)))
            {
                var m = model as AuditedEntity;
                m.CreateUser = CurrentUserName;
                m.CreateTime = DateTime.Now;
                m.UpdateTime = DateTime.Now;
                m.UpdateUser = CurrentUserName;
            }
            _repository.Insert(model);

            return _repository.SaveChanges();
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public virtual int Update(TAddUpdateDto input)
        {
            TEntity model = _mapper.Map<TEntity>(input);

            //判断是否带审计属性
            if (typeof(TEntity).IsSubclassOf(typeof(AuditedEntity)))
            {
                var m = model as AuditedEntity;
                m.UpdateTime = DateTime.Now;
                m.UpdateUser = CurrentUserName;
            }
            _repository.Update(model);

            return _repository.SaveChanges();
        }

        /// <summary>
        /// 删除(真删）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual int Delete(Tkey id)
        {
            _repository.Remove(id);
            return _repository.SaveChanges();
        }

        /// <summary>
        /// 根据ID获取对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual TEntityDto GetById(Tkey id)
        {
            TEntity data =  _repository.GetById(id);
            if(data == null)
            {
                throw new ArgumentNullException("无法获取对象，对象为null");
            }
            return _mapper.Map<TEntityDto>(data);
        }

    }
}
